package com.hdphone.zljutils;


import android.app.Application;
import android.content.Context;
import android.util.Log;

import com.hdphone.zljutils.annotation.PrivacyPolicy;
import com.hdphone.zljutils.impl.ActivityUtilImpl;
import com.hdphone.zljutils.impl.ApkUtilImpl;
import com.hdphone.zljutils.impl.AppOpsUtilImpl;
import com.hdphone.zljutils.impl.AssetsUtilImpl;
import com.hdphone.zljutils.impl.Base64UtilImpl;
import com.hdphone.zljutils.impl.BeanUtilImpl;
import com.hdphone.zljutils.impl.BitmapUtilImpl;
import com.hdphone.zljutils.impl.ClipboardUtilImpl;
import com.hdphone.zljutils.impl.ColorUtilImpl;
import com.hdphone.zljutils.impl.CpuUtilImpl;
import com.hdphone.zljutils.impl.DateUtilImpl;
import com.hdphone.zljutils.impl.DeviceUuidFactoryImpl;
import com.hdphone.zljutils.impl.DimenUtilImpl;
import com.hdphone.zljutils.impl.FileUtilImpl;
import com.hdphone.zljutils.impl.GsonUtilImpl;
import com.hdphone.zljutils.impl.INetwork;
import com.hdphone.zljutils.impl.ImeiUtilImpl;
import com.hdphone.zljutils.impl.IntentUtilImpl;
import com.hdphone.zljutils.impl.KeyboardUtilImpl;
import com.hdphone.zljutils.impl.LocationUtilImpl;
import com.hdphone.zljutils.impl.LogUtilImpl;
import com.hdphone.zljutils.impl.MD5UtilImpl;
import com.hdphone.zljutils.impl.MathUtilImpl;
import com.hdphone.zljutils.impl.MmkvUtilImpl;
import com.hdphone.zljutils.impl.NumberUtilImpl;
import com.hdphone.zljutils.impl.RegexUtilImpl;
import com.hdphone.zljutils.impl.RemoteLogUtilImpl;
import com.hdphone.zljutils.impl.RomUtilImpl;
import com.hdphone.zljutils.impl.ScreenUtilImpl;
import com.hdphone.zljutils.impl.ShellUtilImpl;
import com.hdphone.zljutils.impl.StringUtilImpl;
import com.hdphone.zljutils.impl.ToastUtilImpl;
import com.hdphone.zljutils.impl.UriUtilImpl;
import com.hdphone.zljutils.impl.ViewUtilImpl;
import com.hdphone.zljutils.impl.WidgetUtilImpl;
import com.hdphone.zljutils.impl.WifiUtilImpl;
import com.hdphone.zljutils.inter.IActivityUtil;
import com.hdphone.zljutils.inter.IApkUtil;
import com.hdphone.zljutils.inter.IAppOpsUtil;
import com.hdphone.zljutils.inter.IAssetsUtil;
import com.hdphone.zljutils.inter.IBase64Util;
import com.hdphone.zljutils.inter.IBeanUtil;
import com.hdphone.zljutils.inter.IBitmapUtil;
import com.hdphone.zljutils.inter.IClipboardUtil;
import com.hdphone.zljutils.inter.IColorUtil;
import com.hdphone.zljutils.inter.ICpuUtil;
import com.hdphone.zljutils.inter.IDateUtil;
import com.hdphone.zljutils.inter.IDeviceUuidFactory;
import com.hdphone.zljutils.inter.IDimenUtil;
import com.hdphone.zljutils.inter.IFileUtil;
import com.hdphone.zljutils.inter.IGsonUtil;
import com.hdphone.zljutils.inter.IImeiUtil;
import com.hdphone.zljutils.inter.IIntentUtil;
import com.hdphone.zljutils.inter.IKeyboardUtil;
import com.hdphone.zljutils.inter.ILocationUtil;
import com.hdphone.zljutils.inter.ILogUtil;
import com.hdphone.zljutils.inter.IMD5Util;
import com.hdphone.zljutils.inter.IMathUtil;
import com.hdphone.zljutils.inter.IMmkvUtil;
import com.hdphone.zljutils.inter.INumberUtil;
import com.hdphone.zljutils.inter.IRegexUtil;
import com.hdphone.zljutils.inter.IRemoteLogUtil;
import com.hdphone.zljutils.inter.IRomUtil;
import com.hdphone.zljutils.inter.IScreenUtil;
import com.hdphone.zljutils.inter.IShellUtil;
import com.hdphone.zljutils.inter.IStringUtil;
import com.hdphone.zljutils.inter.IToastUtil;
import com.hdphone.zljutils.inter.IUriUtil;
import com.hdphone.zljutils.inter.IViewUtil;
import com.hdphone.zljutils.inter.IWidgetUtil;
import com.hdphone.zljutils.inter.IWifiUtil;
import com.hdphone.zljutils.inter.NetworkUtilImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author sq
 * @date 2020/10/19
 * @describe
 */
public class ZljUtils {

    private final static String TAG = "ZljUtils";

    private static volatile Application mContext;

    private static final Class<IApkUtil> APK = IApkUtil.class;
    private static final Class<IAssetsUtil> ASSETS = IAssetsUtil.class;
    private static final Class<IBitmapUtil> BITMAP = IBitmapUtil.class;
    private static final Class<IColorUtil> COLOR = IColorUtil.class;
    private static final Class<IDateUtil> DATE = IDateUtil.class;
    private static final Class<IDimenUtil> DIMEN = IDimenUtil.class;
    private static final Class<IFileUtil> FILE = IFileUtil.class;
    private static final Class<IGsonUtil> GSON = IGsonUtil.class;
    private static final Class<IImeiUtil> IMEI = IImeiUtil.class;
    private static final Class<IMathUtil> MATH = IMathUtil.class;
    private static final Class<IMmkvUtil> MMKV = IMmkvUtil.class;
    private static final Class<INumberUtil> NUMBER = INumberUtil.class;
    private static final Class<IRegexUtil> REGEX = IRegexUtil.class;
    private static final Class<IRomUtil> ROM = IRomUtil.class;
    private static final Class<IScreenUtil> SCREEN = IScreenUtil.class;
    private static final Class<IUriUtil> URI = IUriUtil.class;
    private static final Class<IShellUtil> SHELL = IShellUtil.class;
    private static final Class<INetwork> NETWORK = INetwork.class;
    private static final Class<IToastUtil> TOAST = IToastUtil.class;
    private static final Class<ILogUtil> LOG = ILogUtil.class;
    private static final Class<IBase64Util> BASE64 = IBase64Util.class;
    private static final Class<ICpuUtil> CPU = ICpuUtil.class;
    private static final Class<IBeanUtil> BEAN = IBeanUtil.class;
    private static final Class<IClipboardUtil> CLIPBOARD = IClipboardUtil.class;
    private static final Class<IActivityUtil> ACTIVITY = IActivityUtil.class;
    private static final Class<IDeviceUuidFactory> DEVICE_UUID = IDeviceUuidFactory.class;
    private static final Class<IViewUtil> VIEW = IViewUtil.class;
    private static final Class<IIntentUtil> INTENT = IIntentUtil.class;
    private static final Class<IMD5Util> MD5 = IMD5Util.class;
    private static final Class<IKeyboardUtil> KEYBOARD = IKeyboardUtil.class;
    private static final Class<ILocationUtil> LOCATION = ILocationUtil.class;
    private static final Class<IWifiUtil> WIFI = IWifiUtil.class;
    private static final Class<IRemoteLogUtil> REMOTELOG = IRemoteLogUtil.class;
    private static final Class<IWidgetUtil> WIDGET = IWidgetUtil.class;
    private static final Class<IStringUtil> STRING = IStringUtil.class;
    private static final Class<IAppOpsUtil> OPS = IAppOpsUtil.class;


    private static final Map<Class<?>, Object> map = new ConcurrentHashMap<>();

    public static void init(Application application) {
        mContext = application;
        com.tencent.mmkv.MMKV.initialize(application);
    }

    public static Application getApp() {
        if (mContext == null) {
            throw new IllegalStateException("zljutils should be initialized first");
        }
        return mContext;
    }

    private static <T> T createUtilProxy(final T impl) {
        return (T) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (mContext == null) {
                    throw new IllegalStateException("zljutils should be initialized first");
                }

                PrivacyPolicy annotation = method.getAnnotation(PrivacyPolicy.class);
                if (annotation != null) {
                    //TODO
                    Log.d(TAG, "privacy policy required");
                }

                Object invoke = method.invoke(impl, args);
                return invoke;
            }
        });
    }

    private static <T> T get(Class<T> key) {
        if (map.get(key) == null) {
            map.put(key, createUtilProxy(getImplByClass(key)));
        }

        return (T) map.get(key);
    }

    public static IApkUtil APK() {
        return get(APK);
    }

    public static IAssetsUtil ASSETS() {
        return get(ASSETS);
    }

    public static IBitmapUtil BITMAP() {
        return get(BITMAP);
    }

    public static IColorUtil COLOR() {
        return get(COLOR);
    }

    public static IDateUtil DATE() {
        return get(DATE);
    }

    public static IDimenUtil DIMEN() {
        return get(DIMEN);
    }

    public static IFileUtil FILE() {
        return get(FILE);
    }

    public static IGsonUtil GSON() {
        return get(GSON);
    }

    public static IImeiUtil IMEI() {
        return get(IMEI);
    }

    public static IMathUtil MATH() {
        return get(MATH);
    }

    public static IMmkvUtil MMKV() {
        return get(MMKV);
    }

    public static INumberUtil NUMBER() {
        return get(NUMBER);
    }

    public static IRegexUtil REGEX() {
        return get(REGEX);
    }

    public static IRomUtil ROM() {
        return get(ROM);
    }

    public static IScreenUtil SCREEN() {
        return get(SCREEN);
    }

    public static IUriUtil URI() {
        return get(URI);
    }

    public static INetwork NETWORK() {
        return get(NETWORK);
    }

    public static IShellUtil SHELL() {
        return get(SHELL);
    }

    public static IToastUtil TOAST() {
        return get(TOAST);
    }

    public static ILogUtil LOG() {
        return get(LOG);
    }

    public static IBase64Util BASE64() {
        return get(BASE64);
    }

    public static ICpuUtil CPU() {
        return get(CPU);
    }

    public static IBeanUtil BEAN() {
        return get(BEAN);
    }

    public static IClipboardUtil CLIPBOARD() {
        return get(CLIPBOARD);
    }

    public static IActivityUtil ACTIVITY() {
        return get(ACTIVITY);
    }

    public static IDeviceUuidFactory DEVICEUUID() {
        return get(DEVICE_UUID);
    }

    public static IViewUtil VIEW() {
        return get(VIEW);
    }

    public static IIntentUtil INTENT() {
        return get(INTENT);
    }

    public static IMD5Util MD5() {
        return get(MD5);
    }

    public static IKeyboardUtil KEYBOARD() {
        return get(KEYBOARD);
    }

    public static ILocationUtil LOCATION() {
        return get(LOCATION);
    }

    public static IWifiUtil WIFI() {
        return get(WIFI);
    }

    public static IRemoteLogUtil REMOTELOG() {
        return get(REMOTELOG);
    }

    public static IWidgetUtil WIDGET() {
        return get(WIDGET);
    }

    public static IStringUtil STRING() {
        return get(STRING);
    }

    public static IAppOpsUtil OPS() {
        return get(OPS);
    }

    /**
     * 根据class找到具体的实现类 这样做是为了延迟初始化,不存在使用一个工具类把其它的也初始化的情况
     *
     * @param key
     * @return
     */
    public static Object getImplByClass(Class key) {
        if (key == IApkUtil.class) {
            return new ApkUtilImpl();
        } else if (key == IAssetsUtil.class) {
            return new AssetsUtilImpl();
        } else if (key == IBitmapUtil.class) {
            return new BitmapUtilImpl();
        } else if (key == IColorUtil.class) {
            return new ColorUtilImpl();
        } else if (key == IDateUtil.class) {
            return new DateUtilImpl();
        } else if (key == IDimenUtil.class) {
            return new DimenUtilImpl();
        } else if (key == IFileUtil.class) {
            return new FileUtilImpl();
        } else if (key == IGsonUtil.class) {
            return new GsonUtilImpl();
        } else if (key == IImeiUtil.class) {
            return new ImeiUtilImpl();
        } else if (key == IMathUtil.class) {
            return new MathUtilImpl();
        } else if (key == IMmkvUtil.class) {
            return new MmkvUtilImpl();
        } else if (key == INumberUtil.class) {
            return new NumberUtilImpl();
        } else if (key == IRegexUtil.class) {
            return new RegexUtilImpl();
        } else if (key == IRomUtil.class) {
            return new RomUtilImpl();
        } else if (key == IScreenUtil.class) {
            return new ScreenUtilImpl();
        } else if (key == IUriUtil.class) {
            return new UriUtilImpl();
        } else if (key == IShellUtil.class) {
            return new ShellUtilImpl();
        } else if (key == INetwork.class) {
            return new NetworkUtilImpl();
        } else if (key == IToastUtil.class) {
            return new ToastUtilImpl();
        } else if (key == ILogUtil.class) {
            return new LogUtilImpl();
        } else if (key == IBase64Util.class) {
            return new Base64UtilImpl();
        } else if (key == ICpuUtil.class) {
            return new CpuUtilImpl();
        } else if (key == IBeanUtil.class) {
            return new BeanUtilImpl();
        } else if (key == IClipboardUtil.class) {
            return new ClipboardUtilImpl();
        } else if (key == IActivityUtil.class) {
            return new ActivityUtilImpl();
        } else if (key == IDeviceUuidFactory.class) {
            return new DeviceUuidFactoryImpl();
        } else if (key == IViewUtil.class) {
            return new ViewUtilImpl();
        } else if (key == IIntentUtil.class) {
            return new IntentUtilImpl();
        } else if (key == IMD5Util.class) {
            return new MD5UtilImpl();
        } else if (key == IKeyboardUtil.class) {
            return new KeyboardUtilImpl();
        } else if (key == ILocationUtil.class) {
            return new LocationUtilImpl();
        } else if (key == IWifiUtil.class) {
            return new WifiUtilImpl();
        } else if (key == IRemoteLogUtil.class) {
            return new RemoteLogUtilImpl();
        } else if (key == IWidgetUtil.class) {
            return new WidgetUtilImpl();
        } else if (key == IStringUtil.class) {
            return new StringUtilImpl();
        } else if (key == IAppOpsUtil.class) {
            return new AppOpsUtilImpl();
        }
        return null;
    }

}
